home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / recvfax / jobs.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  254 lines

  1. /*    $Header: /usr/people/sam/fax/recvfax/RCS/jobs.c,v 1.25 1994/04/04 18:25:18 sam Rel $
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "defs.h"
  26. #include <sys/file.h>
  27. #include <fcntl.h>
  28. #include <dirent.h>
  29. #include <stdlib.h>
  30. #include <pwd.h>
  31. #include <errno.h>
  32.  
  33. static int
  34. readJob(Job* job)
  35. {
  36.     char line[1024];
  37.     char* cp;
  38.     char* tag;
  39.     FILE* fp;
  40.  
  41.     fp = fopen((char*) job->qfile, "r");
  42.     if (fp == NULL)
  43.     return (0);
  44.     if (flock(fileno(fp), LOCK_SH|LOCK_NB) < 0 && errno == EWOULDBLOCK)
  45.     job->flags |= JOB_LOCKED;
  46.     while (fgets(line, sizeof (line) - 1, fp)) {
  47.     if (line[0] == '#')
  48.         continue;
  49.     if (cp = strchr(line, '\n'))
  50.         *cp = '\0';
  51.     tag = strchr(line, ':');
  52.     if (!tag || !*tag)
  53.         continue;
  54.     *tag++ = '\0';
  55.     while (isspace(*tag))
  56.         tag++;
  57.     if (isCmd("tts")) {
  58.         job->tts = atoi(tag);
  59.     } else if (isCmd("killtime")) {
  60.         job->killtime = strdup(tag);
  61.     } else if (isCmd("number")) {
  62.         job->number = strdup(tag);
  63.     } else if (isCmd("external")) {
  64.         job->external = strdup(tag);
  65.     } else if (isCmd("sender")) {
  66.         job->sender = strdup(tag);
  67.     } else if (isCmd("mailaddr")) {
  68.         job->mailaddr = strdup(tag);
  69.     } else if (isCmd("status")) {
  70.         job->status = strdup(tag);
  71.     } else if (isCmd("modem")) {
  72.         job->modem = strdup(tag);
  73.     }
  74.     }
  75.     if (job->status == NULL)
  76.     job->status = strdup("");
  77.     if (job->modem == NULL)
  78.     job->modem = strdup(MODEM_ANY);
  79.     if (job->external == NULL && job->number != NULL)
  80.     job->external = strdup(job->number);
  81.     if ((job->flags & JOB_LOCKED) == 0)
  82.     (void) flock(fileno(fp), LOCK_UN);
  83.     fclose(fp);
  84.     /* NB: number and sender are uniformly assumed to exist */
  85.     return (job->number != NULL && job->sender != NULL);
  86. }
  87.  
  88. static Job*
  89. newJob(const char* qfile)
  90. {
  91.     Job* job = (Job*) malloc(sizeof(Job));
  92.     memset((char*) job, 0, sizeof (*job));
  93.     job->qfile = malloc(strlen(FAX_SENDDIR) + strlen(qfile) + 2);
  94.     sprintf(job->qfile, "%s/%s", FAX_SENDDIR, qfile);
  95.     return (job);
  96. }
  97.  
  98. static void
  99. freeJob(Job* job)
  100. {
  101.     if (job->qfile)
  102.     free(job->qfile);
  103.     if (job->killtime)
  104.     free(job->killtime);
  105.     if (job->sender)
  106.     free(job->sender);
  107.     if (job->mailaddr)
  108.     free(job->mailaddr);
  109.     if (job->number)
  110.     free(job->number);
  111.     if (job->external)
  112.     free(job->external);
  113.     if (job->status)
  114.     free(job->status);
  115.     if (job->modem)
  116.     free(job->modem);
  117.     free(job);
  118. }
  119.  
  120. Job*
  121. readJobs()
  122. {
  123.     DIR* dirp;
  124.     struct dirent* dentp;
  125.     Job* jobs = 0;
  126.     Job* jobp = 0;
  127.  
  128.     if (!(dirp = opendir(FAX_SENDDIR))) {
  129.     syslog(LOG_ERR, "%s: opendir: %m", FAX_SENDDIR);
  130.     sendError("Problem accessing send directory.");
  131.     done(-1, "EXIT");
  132.     }
  133.     (void) flock(dirp->dd_fd, LOCK_SH);
  134.     for (dentp = readdir(dirp); dentp; dentp = readdir(dirp)) {
  135.     if (dentp->d_name[0] != 'q')
  136.         continue;
  137.     jobp = newJob(dentp->d_name);
  138.     if (jobp) {
  139.         if (readJob(jobp)) {
  140.         jobp->next = jobs;
  141.         jobs = jobp;
  142.         } else
  143.         freeJob(jobp);
  144.     }
  145.     }
  146.     (void) flock(dirp->dd_fd, LOCK_UN);
  147.     closedir(dirp);
  148.     return jobs;
  149. }
  150.  
  151. int
  152. modemMatch(const char* a, const char* b)
  153. {
  154.     return strcmp(a, MODEM_ANY) == 0 || strcmp(b, MODEM_ANY) == 0 ||
  155.     strcmp(a, b) == 0;
  156. }
  157.  
  158. static int
  159. checkUser(const char* requestor, struct passwd* pwd)
  160. {
  161.     char buf[1024];
  162.     char* cp;
  163.  
  164.     buf[0] = '\0';
  165.     if (pwd->pw_gecos) {
  166.     if (pwd->pw_gecos[0] == '&') {
  167.         strcpy(buf, pwd->pw_name);
  168.         strcat(buf, pwd->pw_gecos+1);
  169.         if (islower(buf[0]))
  170.         buf[0] = toupper(buf[0]);
  171.     } else
  172.         strcpy(buf, pwd->pw_gecos);
  173.     if ((cp = strchr(buf,',')) != 0)
  174.         *cp = '\0';
  175.     } else
  176.     strcpy(buf, pwd->pw_name);
  177.     if (debug) {
  178.     if (*buf)
  179.          syslog(LOG_DEBUG, "%s user: \"%s\"", pwd->pw_name, buf);
  180.     else
  181.          syslog(LOG_DEBUG, "name of %s user unknown", pwd->pw_name);
  182.     }
  183.     return (strcmp(requestor, buf) == 0);
  184. }
  185.  
  186. void
  187. applyToJob(const char* modem, char* tag, const char* op, jobFunc* f)
  188. {
  189.     Job** job;
  190.     char* requestor;
  191.     char* arg;
  192.  
  193.     if (!jobList)
  194.     jobList = readJobs();
  195.  
  196.     if ((requestor = strchr(tag, ':')) == 0) {
  197.     protocolBotch("no requestor name for \"%s\" command.", op);
  198.     done(1, "EXIT");
  199.     }
  200.     *requestor++ = '\0';
  201.     arg = strchr(requestor, ':');
  202.     if (arg)
  203.     *arg++ = '\0';
  204.  
  205.     for (job = &jobList; *job; job = &((*job)->next)) {
  206.     char *jobname = (*job)->qfile+strlen(FAX_SENDDIR)+2;
  207.     if (modemMatch(modem, (*job)->modem) && strcmp(jobname, tag) == 0)
  208.         break;
  209.     }
  210.     if (!*job) {
  211.     sendClient("notQueued", "%s", tag);
  212.     return;
  213.     }
  214.     /*
  215.      * Validate requestor is permitted to do op to the
  216.      * requested job.  We permit the person that submitted
  217.      * the job, the fax user, and root.  Using the GECOS
  218.      * field in doing the comparison is a crock, but not
  219.      * something to change now--leave it for a protocol
  220.      * redesign.
  221.      */
  222.     if (strcmp(requestor, (*job)->sender) != 0) {    /* not the sender */
  223.     struct passwd* pwd = getpwuid(getuid());
  224.  
  225.     if (!pwd) {
  226.         syslog(LOG_ERR, "getpwuid failed for uid %d: %m", getuid());
  227.         pwd = getpwuid(geteuid());
  228.     }
  229.     if (!pwd) {
  230.         syslog(LOG_ERR, "getpwuid failed for effective uid %d: %m",
  231.         geteuid());
  232.         sendClient("sOwner", "%s", tag);
  233.         return;
  234.     }
  235.     if (!checkUser(requestor, pwd)) {        /* not fax user */
  236.         pwd = getpwnam("root");
  237.         if (!pwd) {
  238.         syslog(LOG_ERR, "getpwnam failed for \"root\": %m");
  239.         sendClient("sOwner", "%s", tag);
  240.         return;
  241.         }
  242.         if (!checkUser(requestor, pwd)) {        /* not root user */
  243.         sendClient("jobOwner", "%s", tag);
  244.         return;
  245.         }
  246.     }
  247.     }
  248.     if (debug)
  249.     syslog(LOG_DEBUG, "%s request by %s for %s", op, requestor, tag);
  250.     (*f)(*job, tag, arg);
  251.     if ((*job)->flags & JOB_INVALID)
  252.     *job = (*job)->next;
  253. }
  254.